#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<cstdio>
#include<pthread.h>
#include"thread.hpp"
#include"lockGuard.hpp"
#include"log.hpp"


const int g_default_num=3;

template<class T>
class threadPool
{
public:
    pthread_mutex_t* getlock()
    {
        return &mtx_;
    }
    void wait()
    {
        pthread_cond_wait(&cond_,&mtx_);
    }

    bool isEmpty()
    {
        return TaskQueue_.empty();
    }

    T getTask()
    {
        T t=TaskQueue_.front();
        TaskQueue_.pop();
        return t;
    }

public:
    threadPool(int num=g_default_num):num_(num)
    {
        for(int i=1;i<=num_;i++)
        {
            threads_.push_back(new thread(i,routine,this));
        }

        pthread_mutex_init(&mtx_,nullptr);
        pthread_cond_init(&cond_,nullptr);
    }

    void run()
    {
        for(auto &its:threads_)
        {
            its->start();
            //std::cout<<its->name()<<"启动"<<std::endl;
            logMessage(NORMAL, "%s %s", its->name().c_str(), "启动成功");
        }
    }

    //消费过程
    static void*routine(void*args)
    {
        threadData*td=(threadData*)args;
        threadPool<T>*tp=(threadPool<T>*)td->args;

        while(true)
        {
            T Task;
           {
            lockGuard lock(tp->getlock());
            while(tp->isEmpty()) tp->wait();

           Task=tp->getTask();
           }

         Task(td->name);
        }

            return nullptr;
    }

    //生产过程
    void pushTask(const T& in)
    {
        lockGuard lock(&mtx_);
        TaskQueue_.push(in);
        pthread_cond_signal(&cond_);
    }

    ~threadPool()
    {
        for(auto &its:threads_)
        {
            its->join();
            delete its;
        }

        pthread_mutex_destroy(&mtx_);
        pthread_cond_destroy(&cond_);
    }

private:
    std::vector<thread*> threads_;
    int num_;
    std::queue<T> TaskQueue_;
    pthread_mutex_t mtx_;
    pthread_cond_t cond_;
};